package com.ts.api.module.product.biz.impl;

import com.gitee.apanlh.util.base.CollUtils;
import com.gitee.apanlh.util.base.Eq;
import com.gitee.apanlh.util.base.IteratorUtils;
import com.gitee.apanlh.util.base.MapUtils;
import com.gitee.apanlh.util.date.DateUtils;
import com.gitee.apanlh.util.log.Log;
import com.gitee.apanlh.util.reflection.ClassConvertUtils;
import com.gitee.apanlh.util.valid.Assert;
import com.gitee.apanlh.util.valid.ValidParam;
import com.ts.api.common.constant.api.ApiEnum;
import com.ts.api.common.constant.common.SwitchEnum;
import com.ts.api.common.constant.product.ProductPlanVersionEnum;
import com.ts.api.common.constant.product.ProductPlanVersionMode;
import com.ts.api.common.constant.productflow.ProductApplyFlowStatusEnum;
import com.ts.api.common.context.ApiContext;
import com.ts.api.common.localcache.DistrictCache;
import com.ts.api.common.redis.ApiMatchPhoneMaskRedisKey;
import com.ts.api.common.redis.ApiMatchRedisKey;
import com.ts.api.common.redis.ChannelMatchRedisKey;
import com.ts.api.common.redis.DataExchangeRedisKey;
import com.ts.api.common.redis.MatchProductPlanRedisKey;
import com.ts.api.common.redis.Md5DataFilterRedisKey;
import com.ts.api.common.redis.entity.ApiMatchPhoneMaskRedisCache;
import com.ts.api.common.util.OpenTimeUtils;
import com.ts.api.exp.ApiMsgException;
import com.ts.api.module.api.convert.core.http.client.ApiHttpMessage;
import com.ts.api.module.api.convert.org.model.RespOrgPhoneMaskDataExchange;
import com.ts.api.module.api.convert.plan.http.ApiPlanHttpHandler;
import com.ts.api.module.api.convert.platform.entity.RespPlatformFederateForm;
import com.ts.api.module.api.convert.platform.entity.RespPlatformMultiPhoneMaskDataExchange;
import com.ts.api.module.api.convert.platform.entity.RespPlatformPhoneMaskDataExchange;
import com.ts.api.module.api.convert.platform.entity.RespPlatformPhoneMd5DataExchange;
import com.ts.api.module.api.entity.ApiUserRequest;
import com.ts.api.module.api.entity.bo.ApiBizMatchBO;
import com.ts.api.module.api.entity.po.ApiKeyPO;
import com.ts.api.module.api.entity.vo.ReqApiParameterVO;
import com.ts.api.module.api.service.ApiBizRequiredService;
import com.ts.api.module.common.entity.DistrictPO;
import com.ts.api.module.product.biz.ProductMatchBiz;
import com.ts.api.module.product.entity.po.ProductApplyFlowPO;
import com.ts.api.module.product.entity.po.ProductPO;
import com.ts.api.module.product.entity.po.ProductPlanFieldPO;
import com.ts.api.module.product.entity.po.ProductPlanPO;
import com.ts.api.module.product.entity.qo.ProductPlanFieldQO;
import com.ts.api.module.product.entity.qo.ProductPlanQO;
import com.ts.api.module.product.service.ProductApplyFlowService;
import com.ts.api.module.product.service.ProductPlanFieldService;
import com.ts.api.module.product.service.ProductPlanService;
import com.ts.api.module.product.service.ProductPlanTypeService;
import com.ts.api.module.product.service.ProductService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.concurrent.Callable;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

@Service
public class ProductMatchBizImpl implements ProductMatchBiz {

    @Autowired
    private ProductPlanService productPlanService;
    @Autowired
    private ProductPlanFieldService productPlanFieldService;
    @Autowired
    private ProductPlanTypeService productPlanTypeService;
    @Autowired
    private ProductService productService;
    @Autowired
    private ApiPlanHttpHandler apiPlanHttpHandler;
    @Autowired
    private ApiBizRequiredService apiBizRequiredService;
    @Autowired
    private ProductApplyFlowService productApplyFlowService;

    @Override
    @Transactional(readOnly = true)
    public List<ProductPlanPO> apiMatchPlan(ApiKeyPO apiKeyPO, ReqApiParameterVO reqApiParameterVO, ApiBizMatchBO apiBizMatchBO) {
        Map<String, String> userForm = reqApiParameterVO.getFormMap();
        BigDecimal apiChannelPrice = apiKeyPO.getApiPrice();

        DistrictPO districtPO = DistrictCache.getByName(userForm.get("city"));
        Assert.isNotNullThrows(districtPO, new ApiMsgException(ApiEnum.API_DATA_EXCHANGE_AREA_ERROR));

        //  搜索项符合的计划类型及关联的地区匹配
        List<Integer> listMathPlanType = apiBizMatchBO.listPlanToListInt();
        ProductPlanQO productPlanQO = ProductPlanQO.createAreaName(districtPO.getName());
        productPlanQO.setListPlanType(listMathPlanType);
        productPlanQO.setEnvType(apiKeyPO.getApiEnvType());
        List<ProductPlanPO> list = productPlanService.list(productPlanQO);
        Assert.isNotEmptyThrows(list, new ApiMsgException(ApiEnum.API_DATA_EXCHANGE_MATCH_AREA_EMPTY));

        //  过滤开放时间
        List<ProductPlanPO> listProductPlanPO = OpenTimeUtils.filter(list);
        Assert.isNotEmptyThrows(listProductPlanPO, new ApiMsgException(ApiEnum.API_DATA_EXCHANGE_MATCH_PLAN_TIME_EMPTY));

        //  匹配主体计划集合
        List<ProductPlanPO> listMatchPlan = CollUtils.newArrayList();
        //  根据计划id分组后独立筛选符合计划
        List<ProductPlanFieldPO> listProductPlanForm = productPlanFieldService.listProductPlanField(ProductPlanFieldQO.create(listProductPlanPO));
        IteratorUtils.entrySet(CollUtils.groupByToLinked(listProductPlanForm, t -> t.getProductPlanId()), (planId, listPlanForm) -> {
            //  根据计划id获取计划对象
            ProductPlanPO productPlanPO = CollUtils.findOne(listProductPlanPO, t -> Eq.object(t.getId(), planId));

            //  验证资质符合
            boolean requiredPlanField = apiBizRequiredService.requiredPlanField(listPlanForm, userForm);
            if (!requiredPlanField) {
                return ;
            }

            //  分润模式忽略跳过
            BigDecimal share = productPlanPO.getShare();
            if (!Eq.str(share.toString(), "0.00")) {
                //  添加符合计划
                listMatchPlan.add(productPlanPO);
                return ;
            }

            //  验证单价是否超过当前渠道价格
            boolean requiredPlanPrice = apiBizRequiredService.requiredPlanPrice(productPlanPO, apiChannelPrice);
            if (!requiredPlanPrice) {
                return ;
            }
            //  添加符合计划
            listMatchPlan.add(productPlanPO);
        });

        Assert.isNotEmptyThrows(listMatchPlan, new ApiMsgException(ApiEnum.API_DATA_EXCHANGE_MATCH_EMPTY));
        return listMatchPlan;
    }

    @Override
    public ProductPlanPO apiAllocateByPrice(ApiKeyPO apiKeyPO, ReqApiParameterVO reqApiParameterVO, List<ProductPlanPO> listMatchPlan) {
        Assert.isNotEmptyThrows(listMatchPlan, new ApiMsgException(ApiEnum.API_DATA_EXCHANGE_MATCH_FAIL2));

        Map<String, String> mapReqForm = reqApiParameterVO.getFormMap();
        String phoneMd5 = mapReqForm.get("phoneMd5");
        Long reqId = ClassConvertUtils.toLong(ApiContext.REQ_ID.get());
        String reqIdStr = String.valueOf(reqId);

        //  渠道信息
        Integer apiEnvType = apiKeyPO.getApiEnvType();
        String apiClientId = apiKeyPO.getApiClientId();
        Long loanChannelId = apiKeyPO.getLoanChannelId();
        BigDecimal apiChannelPrice = apiKeyPO.getApiPrice();

        //  已匹配的机构-线程安全
        List<ProductPlanPO> chooseMatchPlan = new CopyOnWriteArrayList<>();
        //  已匹配计划的流程-线程安全
        Map<Long, ProductApplyFlowPO> applyFlowMap = MapUtils.newConcurrentHashMap();
        //  城市逻辑
        DistrictPO districtPO = DistrictCache.getByName(mapReqForm.get("city"));

        //  匹配计划逻辑
        try (ExecutorService pool = Executors.newVirtualThreadPerTaskExecutor()) {
            List<Callable<ProductPlanPO>> callables = CollUtils.newArrayList();

            for (ProductPlanPO productPlanPO : listMatchPlan) {
                callables.add(() -> {
                    //  获取主体计划信息
                    Long productPlanId = productPlanPO.getId();
                    Long loanProductId = productPlanPO.getLoanProductId();
                    //  获取主体信息
                    ProductPO productPO = productService.get(loanProductId);
                    String apiDataExchange = productPO.getApiDataExchange();

                    //  判断是否API机构计划或平台计划
                    boolean hasPlatform = productPlanTypeService.hasPlatformPlan(productPlanPO);
                    //  是否平台分润
                    boolean hasPlatShare = productPlanTypeService.hasPlatShare(productPlanPO);
                    //  是否本地机构计划
                    boolean hasLocalOrgPlan = productPlanTypeService.hasLocalOrgPlan(productPO, productPlanPO);
                    //  是否特殊计划
                    boolean hasLocalSpecialPlan = productPlanTypeService.hasLocalSpecialPlan(productPO, productPlanPO);

                    //  记录流程日志
                    ProductApplyFlowPO insertProductApplyFlowPO = new ProductApplyFlowPO();
                    insertProductApplyFlowPO.setApiClientId(apiClientId);
                    insertProductApplyFlowPO.setLoanChannelId(loanChannelId);
                    insertProductApplyFlowPO.setLoanProductId(loanProductId);
                    insertProductApplyFlowPO.setLoanProductPlanId(productPlanId);
                    insertProductApplyFlowPO.setCallUrl(apiDataExchange);
                    insertProductApplyFlowPO.setPhoneMd5(phoneMd5);
                    insertProductApplyFlowPO.setCreateTime(DateUtils.currentTime());
                    insertProductApplyFlowPO.setStatus(ProductApplyFlowStatusEnum.DATA_EXCHANGE_SUC.getType());
                    insertProductApplyFlowPO.setReqId(reqId);
                    insertProductApplyFlowPO.setBizStatus("0");
                    insertProductApplyFlowPO.setAreaCode(districtPO.getCode());
                    insertProductApplyFlowPO.setAreaName(districtPO.getName());

                    //  判断是否渠道被屏蔽
                    boolean hasChannelFilter = apiBizRequiredService.hasChannelFilter(insertProductApplyFlowPO, productPlanPO, loanChannelId, ProductApplyFlowStatusEnum.DATA_EXCHANGE_BIZ_FAIL);
                    if (hasChannelFilter) {
                        return null;
                    }
                    //  平台计划版本验证，API渠道版本于平台计划版本是否为同一种类型（全流程对全流程，半流程对半流程）
                    boolean requiredApiChannelPlanVersion = apiBizRequiredService.requiredApiChannelPlanVersion(apiKeyPO, productPlanPO);
                    if (!requiredApiChannelPlanVersion) {
                        return null;
                    }
                    //  判断计划限量
                    boolean hasLimitTotal = apiBizRequiredService.hasLimitTotal(insertProductApplyFlowPO, productPlanPO, ProductApplyFlowStatusEnum.DATA_EXCHANGE_BIZ_FAIL);
                    if (hasLimitTotal) {
                        return null;
                    }
                    //  MD5库排重
                    boolean hasExistMd5Filter = apiBizRequiredService.hasExistMd5Filter(insertProductApplyFlowPO, productPlanPO, phoneMd5, ProductApplyFlowStatusEnum.DATA_EXCHANGE_BIZ_FAIL);
                    if (hasExistMd5Filter) {
                        return null;
                    }
                    //  验证机构余额是否足够本次扣款
                    boolean requiredProductAmount = apiBizRequiredService.requiredProductAmount(insertProductApplyFlowPO, productPlanPO, ProductApplyFlowStatusEnum.DATA_EXCHANGE_BIZ_FAIL);
                    if (!requiredProductAmount) {
                        return null;
                    }

                    //  本地推送
                    if (hasLocalOrgPlan || hasLocalSpecialPlan) {
                        if (hasLocalOrgPlan) {
                            insertProductApplyFlowPO.setReqData("本地甲方CRM");
                        }
                        if (hasLocalSpecialPlan) {
                            insertProductApplyFlowPO.setReqData("特殊本地甲方CRM");
                        }
                        //  本地计划分发
                        applyFlowMap.put(productPlanId, insertProductApplyFlowPO);
                        return productPlanPO;
                    }

                    //  http分发逻辑
                    ApiUserRequest copyApiUserRequest = ClassConvertUtils.toBean(mapReqForm, ApiUserRequest.class);
                    copyApiUserRequest.setProductId(loanProductId);
                    copyApiUserRequest.setProductPlanId(productPlanId);
                    copyApiUserRequest.setEnvType(apiEnvType);
                    copyApiUserRequest.setLoanChannelId(loanChannelId);
                    copyApiUserRequest.setReqId(reqIdStr);
                    copyApiUserRequest.setProvinceCode(districtPO.getProvinceCode());
                    copyApiUserRequest.setProvinceName(districtPO.getProvinceName());

                    //  根据计划类型区分手机号传输模式
                    Integer planVersionMode = productPlanPO.getVersionMode();
                    //  手机号掩码模式
                    if (Eq.objectOr(planVersionMode,
                            ProductPlanVersionMode.PHONE_MASK_8.getVersionMode(),
                            ProductPlanVersionMode.PHONE_MASK_9.getVersionMode(),
                            ProductPlanVersionMode.PHONE_MASK_10.getVersionMode())) {

                        ProductPlanVersionMode productPlanVersionMode = ProductPlanVersionMode.getEnum(planVersionMode);
                        String phone = copyApiUserRequest.getPhone();
                        String phoneMask = phone.substring(0, productPlanVersionMode.getCutSize());
                        copyApiUserRequest.setPhoneMask(phoneMask);
                    }

                    //  发起HTTP撞库
                    ApiHttpMessage httpMessage = apiPlanHttpHandler.sendApiDataExchange(apiKeyPO, copyApiUserRequest, productPO, productPlanPO);
                    insertProductApplyFlowPO.setCallUrl(productPO.getApiApplyUrl());
                    insertProductApplyFlowPO.setSourceReqData(httpMessage.getSourceRequestBody());
                    insertProductApplyFlowPO.setReqData(String.valueOf(httpMessage.getRequestBody()));
                    insertProductApplyFlowPO.setRespData(httpMessage.getResponseBody());
                    insertProductApplyFlowPO.setRespCode(String.valueOf(httpMessage.getRespCode()));

                    //  是否HTTP超时
                    boolean hasRespTimeout = apiBizRequiredService.hasHttpTimeOut(insertProductApplyFlowPO, httpMessage, ProductApplyFlowStatusEnum.DATA_EXCHANGE_REQ_TIMEOUT);
                    if (hasRespTimeout) {
                        return null;
                    }

                    //  是否HTTP异常
                    boolean hasHttpExp = apiBizRequiredService.hasHttpExp(insertProductApplyFlowPO, httpMessage, true, ProductApplyFlowStatusEnum.DATA_EXCHANGE_EXCEPTION);
                    if (hasHttpExp) {
                        return null;
                    }

                    //  返回业务验证
                    boolean hasHttpRespBizSuc;
                    if (hasPlatform) {
                        //  平台是否返回成功
                        hasHttpRespBizSuc = apiBizRequiredService.hasHttpRespBizSuc(insertProductApplyFlowPO, httpMessage, true, ProductApplyFlowStatusEnum.PLAT_FORM_DATA_EXCHANGE_FAIL);
                    } else {
                        //  除平台所有计划都走此接口
                        hasHttpRespBizSuc = apiBizRequiredService.hasHttpRespBizSuc(insertProductApplyFlowPO, httpMessage, true, ProductApplyFlowStatusEnum.DATA_EXCHANGE_FAIL);
                    }
                    if (!hasHttpRespBizSuc) {
                        return null;
                    }

                    //  平台计划解析返回结果
                    if (hasPlatform) {
                        Integer versionMode = productPlanPO.getVersionMode();

                        //  联登模式判断
                        if (ProductPlanVersionMode.FEDERATE_FORM.hasVersionMode(versionMode)) {
                            RespPlatformFederateForm respPlatformFederateForm = apiBizRequiredService.requiredPlatFormFederateDataExchange(insertProductApplyFlowPO, httpMessage);
                            if (!respPlatformFederateForm.getHasBizSuc()) {
                                insertProductApplyFlowPO.setStatus(ProductApplyFlowStatusEnum.DATA_EXCHANGE_FAIL.getType());
                                insertProductApplyFlowPO.setExceptionMsg("下游联登表单-返回业务失败");
                                productApplyFlowService.insert(insertProductApplyFlowPO, true);
                                return null;
                            }
                            //  将属性覆盖原有计划实体
                            productPlanPO.setTempCallUrl(respPlatformFederateForm.getCallUrl());
                            //  保存流程记录
                            applyFlowMap.put(productPlanId, insertProductApplyFlowPO);
                            return productPlanPO;
                        }

                        //  手机号md5模式
                        if (ProductPlanVersionMode.MD5.hasVersionMode(versionMode)) {
                            RespPlatformPhoneMd5DataExchange apiPlatFormDataExchange = apiBizRequiredService.requiredPlatformDataExchange(insertProductApplyFlowPO, httpMessage, hasPlatShare, productPlanPO);
                            if (!apiPlatFormDataExchange.getHasBizSuc()) {
                                return null;
                            }

                            String logo = apiPlatFormDataExchange.getLogoPath();
                            String productName = apiPlatFormDataExchange.getProductName();
                            String displayName = apiPlatFormDataExchange.getDisplayName();

                            //  最终价格
                            BigDecimal finalPrice;
                            //  分润模式
                            if (hasPlatShare) {
                                finalPrice = apiPlatFormDataExchange.calculateSharePrice(productPlanPO.getShare());
                            } else {
                                finalPrice = productPlanPO.getPrice();
                            }

                            //  将属性覆盖原有计划实体
                            productPlanPO.setPrice(finalPrice);
                            productPlanPO.setLogoPath(logo);
                            productPlanPO.setDisplayName(productName);
                            productPlanPO.setTempProductName(displayName);
                            productPlanPO.setTempCallUrl(apiPlatFormDataExchange.getCallUrl());
                            productPlanPO.setTempApplyId(apiPlatFormDataExchange.getApplyId());

                            //  验证是否是半流程授权模式
                            if (ProductPlanVersionEnum.AUTH_NOTICE_CALL.hasVersion(productPlanPO.getVersionType())) {
                                String dataExchangeUniqueIdByPhoneMd5 = ApiMatchRedisKey.getDataExchangeUniqueIdByPhoneMd5(loanProductId, productPlanId, phoneMd5);
                                ChannelMatchRedisKey.CHANNEL_APPLY_NOTICE_FLOW.setForMinutes(dataExchangeUniqueIdByPhoneMd5, insertProductApplyFlowPO, 10L);
                            }

                            applyFlowMap.put(productPlanId, insertProductApplyFlowPO);
                            return productPlanPO;
                        }

                        //  掩码模式判断
                        if (ProductPlanVersionMode.PHONE_MASK_8.hasVersionMode(versionMode)) {
                            RespPlatformMultiPhoneMaskDataExchange respPlatformMultiPhoneMaskDataExchange = apiBizRequiredService.requiredPlatformPhoneMaskDataExchange(insertProductApplyFlowPO, httpMessage, hasPlatShare, productPlanPO);
                            if (!respPlatformMultiPhoneMaskDataExchange.getHasBizSuc()) {
                                Log.get().error("{}", "自有渠道掩码模式返回空对象");
                                return null;
                            }

                            //  筛选可匹配项
                            List<RespPlatformPhoneMaskDataExchange> listSucMatch = CollUtils.newArrayList();
                            List<RespPlatformPhoneMaskDataExchange> listPhoneMask = respPlatformMultiPhoneMaskDataExchange.getListPhoneMask();
                            for (RespPlatformPhoneMaskDataExchange respPlatformPhoneMaskDataExchange: listPhoneMask) {
                                //  验证手机号明文中，其中listPhoneMd5中是否包含其中-如果返回空则代表可匹配-或如果对方返回的MD5不包含在我们之内，则认定可以匹配
                                List<String> listPhoneMd5Result = respPlatformPhoneMaskDataExchange.getListPhoneMd5();
                                if (ValidParam.isEmpty(listPhoneMd5Result) || !listPhoneMd5Result.contains(phoneMd5)) {
                                    listSucMatch.add(respPlatformPhoneMaskDataExchange);
                                }
                            }

                            //  如果为空则代表都存在，跳过匹配流程
                            if (ValidParam.isEmpty(listSucMatch)) {
                                insertProductApplyFlowPO.setStatus(ProductApplyFlowStatusEnum.DATA_EXCHANGE_FAIL.getType());
                                insertProductApplyFlowPO.setExceptionMsg("下游平台-掩码-返回md5中全部都包含-匹配失败");
                                productApplyFlowService.insert(insertProductApplyFlowPO, true);
                                return null;
                            }

                            //  价格排序
                            listSucMatch.sort(Comparator.comparing(phoneMaskDataExchange -> phoneMaskDataExchange.getPrice(), Comparator.reverseOrder()));
                            RespPlatformPhoneMaskDataExchange first = listSucMatch.getFirst();

                            String logo = first.getLogoPath();
                            String productName = first.getProductName();
                            String companyName = first.getDisplayName();

                            //  最终价格
                            BigDecimal finalPrice;
                            //  分润模式
                            if (hasPlatShare) {
                                finalPrice = first.calculateSharePrice(productPlanPO.getShare());
                            } else {
                                finalPrice = productPlanPO.getPrice();
                            }

                            //  将属性覆盖原有计划实体
                            productPlanPO.setPrice(finalPrice);
                            productPlanPO.setLogoPath(logo);
                            productPlanPO.setDisplayName(productName);
                            productPlanPO.setTempProductName(companyName);
                            productPlanPO.setTempCallUrl(first.getCallUrl());
                            productPlanPO.setTempApplyId(first.getApplyId());

                            //  保存掩码applyId值
                            String saveApplyKey = ApiMatchPhoneMaskRedisKey.getChannelDataExchangeApplyIdKey(loanChannelId, loanProductId, productPlanId, phoneMd5);

                            ApiMatchPhoneMaskRedisCache apiMatchPhoneMaskRedisCache = new ApiMatchPhoneMaskRedisCache();
                            apiMatchPhoneMaskRedisCache.setDataExchangeReqId(reqId.toString());
                            apiMatchPhoneMaskRedisCache.setApplyId(first.getApplyId());
                            apiMatchPhoneMaskRedisCache.setProductId(productPO.getId());
                            apiMatchPhoneMaskRedisCache.setProductPlanId(productPlanPO.getId());

                            ApiMatchPhoneMaskRedisKey.CHANNEL_DATA_EXCHANGE_PHONE_MASK_APPLY_ID.setForMinutes(saveApplyKey, apiMatchPhoneMaskRedisCache, 10l);

                            applyFlowMap.put(productPlanId, insertProductApplyFlowPO);
                            return productPlanPO;
                        }
                    } else {
                        //  机构计划掩码模式判断
                        if (ProductPlanVersionMode.PHONE_MASK_8.hasVersionMode(planVersionMode)) {
                            //  获取掩码实体
                            RespOrgPhoneMaskDataExchange respOrgPhoneMaskDataExchange = apiBizRequiredService.respOrgDataExchange(insertProductApplyFlowPO, httpMessage, hasPlatShare, productPlanPO);

                            //  验证手机号明文中，其中listPhoneMd5中是否包含其中
                            List<String> listPhoneMd5 = respOrgPhoneMaskDataExchange.getListPhoneMd5();
                            //  传递空，则非法返回null
                            if (ValidParam.isNull(listPhoneMd5)) {
                                insertProductApplyFlowPO.setStatus(ProductApplyFlowStatusEnum.DATA_EXCHANGE_FAIL.getType());
                                insertProductApplyFlowPO.setExceptionMsg("下游机构-掩码-返回md5列表为空");
                                productApplyFlowService.insert(insertProductApplyFlowPO, true);
                                return null;
                            }

                            //  如果返回空则代表可匹配-或如果对方返回的MD5不包含在我们之内，则认定可以匹配
                            if (ValidParam.isEmpty(listPhoneMd5) || !listPhoneMd5.contains(phoneMd5)) {
                                applyFlowMap.put(productPlanId, insertProductApplyFlowPO);
                                return productPlanPO;
                            }
                            //  走到这里的情况只有我方phoneMd5，包含在对方返回的md5集合之内
                            insertProductApplyFlowPO.setStatus(ProductApplyFlowStatusEnum.DATA_EXCHANGE_FAIL.getType());
                            insertProductApplyFlowPO.setExceptionMsg("下游机构-掩码-返回md5中全部都包含-匹配失败");
                            productApplyFlowService.insert(insertProductApplyFlowPO, true);
                            return null;
                        }
                    }

                    //  二次验证平台计划回传价格是否低于当前渠道价
                    if (!apiBizRequiredService.requiredPlanPrice(productPlanPO, apiChannelPrice)) {
                        return null;
                    }

                    //  保存流程记录
                    applyFlowMap.put(productPlanId, insertProductApplyFlowPO);
                    return productPlanPO;
                });
            }

            //  异步回调
            try {
                List<ProductPlanPO> futures = pool.invokeAll(callables, apiKeyPO.getApiTimeoutLimit() - 200, TimeUnit.MILLISECONDS)
                    .stream()
                    .filter(future -> future.state() == Future.State.SUCCESS && ValidParam.isNotNull(future))
                    .map(future -> future.resultNow())
                .toList();

                for (ProductPlanPO productPlanPO : futures) {
                    if (ValidParam.isNotNull(productPlanPO)) {
                        chooseMatchPlan.add(productPlanPO);
                    }
                }
            } catch (Exception e) {
                //  do noting
            }
        }

        //  如果都没匹配到的直接放弃
        Assert.isNotEmptyThrows(chooseMatchPlan, new ApiMsgException(ApiEnum.API_DATA_EXCHANGE_MATCH_FAIL));

        //  价格排序
        chooseMatchPlan.sort(Comparator.comparing(ProductPlanPO::getPrice, Comparator.reverseOrder())
            //  本地机构排序-本地机构优先
            .thenComparing(ProductPlanPO::getPriorityLocalOrg, Comparator.reverseOrder())
        );

        //  匹配失败重置md5过滤状态
        Md5DataFilterRedisKey.MD5_EXIST_FILTER.setForSeconds(phoneMd5, false, 10);

        //  搜索同价格被分发次数最少的机构计划-插入机构撞库成功日志
        ProductPlanPO matchPlan = this.searchSamePriceAllocate(chooseMatchPlan);
        ProductApplyFlowPO productApplyFlowPO = applyFlowMap.get(matchPlan.getId());
        productApplyFlowPO.setBizStatus("1");
        productApplyFlowService.insert(productApplyFlowPO, false);

        //  异步保存多推逻辑
        List<ProductPlanPO> listEnableMultiPlan = CollUtils.find(chooseMatchPlan, t -> SwitchEnum.hasEnable(t.getEnableMultiPush()));
        if (ValidParam.isNotEmpty(listEnableMultiPlan) && listEnableMultiPlan.size() > 1) {
            String multiPushKey = apiClientId + ":" + phoneMd5;
            Thread.ofVirtual().start(() -> {
                //  过滤掉已经获取到的匹配机构
                for (ProductPlanPO multiPlan : listEnableMultiPlan) {
                    Long multiPlanId = multiPlan.getId();

                    //  过滤已经最优匹配过的机构
                    if (Eq.object(matchPlan.getId(), multiPlanId)) {
                        continue;
                    }

                    //  记录多推流程
                    ProductApplyFlowPO multiPlanFlowPO = applyFlowMap.get(multiPlanId);
                    DataExchangeRedisKey.MULTI_PUSH.rightPush(multiPushKey, multiPlanFlowPO);
                }
                DataExchangeRedisKey.MULTI_PUSH.expire(multiPushKey, DateUtils.getTomorrowMidnightMillis(), TimeUnit.MILLISECONDS);
            });
        }
        return matchPlan;
    }

    @Override
    public ProductPlanPO searchSamePriceAllocate(List<ProductPlanPO> listMatchPlan) {
        //  最小被分发的计划
        TreeMap<Integer, ProductPlanPO> minProductPlanMap = new TreeMap<>();

        //  同价位平均分配分发-避免出现分发不均匀
        Map<BigDecimal, List<ProductPlanPO>> priceMap = CollUtils.groupByToLinked(listMatchPlan, ProductPlanPO::getPrice);
        Iterator<Map.Entry<BigDecimal, List<ProductPlanPO>>> priceMapIterator = IteratorUtils.entrySet(priceMap);

        //  搜索最小分发机构次数
        while (priceMapIterator.hasNext()) {
            Map.Entry<BigDecimal, List<ProductPlanPO>> next = priceMapIterator.next();
            List<ProductPlanPO> listProductPlanPO = next.getValue();
            //  如果存在两个同价格才开始搜索
            if (listProductPlanPO.size() <= 1) {
                minProductPlanMap.put(1, IteratorUtils.getFirst(listProductPlanPO));
                break;
            }

            //  搜索同价格未被分发过的机构计划
            for (ProductPlanPO productPlanPO : listProductPlanPO) {
                Object increment = MatchProductPlanRedisKey.PRICE_PRODUCT_PLAN.get(ClassConvertUtils.toStr(productPlanPO.getId()));
                //  此机构计划从未参与分发时将直接返回
                if (increment == null) {
                    minProductPlanMap.put(1, productPlanPO);
                    break;
                }
                Integer incrementInt = ClassConvertUtils.toInt(increment);
                minProductPlanMap.put(incrementInt, productPlanPO);
            }
            //  退出循环
            break;
        }

        //  获取首个元素-记录redis操作-->自增计划-->并设置今日都明日0点自动清理
        ProductPlanPO minAllocateProductPlan = minProductPlanMap.firstEntry().getValue();
        String key = ClassConvertUtils.toStr(minAllocateProductPlan.getId());

        MatchProductPlanRedisKey.PRICE_PRODUCT_PLAN.increment(key);

        long tomorrowMidnightMillis = DateUtils.getTomorrowMidnightMillis();
        MatchProductPlanRedisKey.PRICE_PRODUCT_PLAN.expire(key, tomorrowMidnightMillis, TimeUnit.MILLISECONDS);
        return minAllocateProductPlan;
    }

}
